;(function($){
  $.fn.extend({
    /**
     * .imgload
     * ========
     *
     * [ for a single complete function see: .imgsload ]
     *
     * Execute load method or optional error method
     * for each image in collection at the time the
     * event fires
     *
     * @param  {Function} callback - loaded event function
     * @param  {[type]}   errorfn  - error event function
     * @return {[jQuery collection]} the originating collection
     */
    imgload: function(callback, errorfn)
    {
      return this.each(function(){

        var $img = $(this),
            src = $img.attr('src'),
            $tmp = $('<img>').hide().load(function(){
              callback.apply($img[0]);
              $(this).remove();
            });

        if(!!errorfn) {
          $tmp.error(function(){
            errorfn.apply($img[0]);
            $(this).remove();
          });
        }

        $img.after($tmp);

        $tmp.attr('src',src);
      });
    },
    /**
     * .imgsload
     * =========
     *
     * Wait until all images have loaded then execute one function
     *
     * @param  {[function]} complete
     *         argument one is another jQuery collection
     *         of images that failed (if any) and can be
     *         used to filter and remove/exclude from process
     *
     * @return {[jQuery collection]} the originating collection
     *
     * Example
     * =======
     * $('img').imgsload(function( $failed ){
     *   // filter out any failed images from process using .not
     *   // I generally remove the failed images from the dom at the same time
     *   // all this is optional
     *
     *   // this is the originating collection
     *   $(this).not( $failed.remove() ).each(function(){
     *     // do stuff
     *     // or this could be another plugin method
     *     // instead of an each loop
     *   });
     * });
     *
     * NB: if using a cached collection and you want
     *     to filter out failed images the cache needs
     *     to be set to the new filtered collection
     *     ie.
     *     $cached = $('img');
     *     $('img').imgsload(function( $failed ){
     *       $cached = $(this).not( $failed );
     *     });
     */
    imgsload: function(complete)
    {
      var $collection = $(this),
          $failed = $(),
          waiting = $collection.length,
          loaded = function(e)
          {
            waiting--;
            if(waiting<=0) {
              complete.apply($collection, [$failed]);
            }
          },
          failed = function()
          {
            $failed = $failed.add(this);
            waiting--;
            if(waiting<=0) loaded();
          };

      $collection.imgload(loaded, failed);

      if($collection.length===0) loaded();

      return $collection;
    }
  });

  /**
   * Legacy plugin method names
   */
  $.fn.extend({
    /**
     * @deprecated
     * see: imgload
     */
    xbonload: $.fn.imgload,
    /**
     * @deprecated
     * see: imgsload
     */
    xbonloadall: $.fn.imgsload
  });

})(jQuery);

// feature tiles
jQuery(function($){
  var $wrap = $('#home-features'),
      $inner = $('.inner', $wrap),
      $features = $('.feature', $wrap),
      $featureContents = $('.feature-content', $wrap),
      $featureImgs = $('.feature-img',$wrap),
      $imgs = $('img', $featureImgs).imgsload(function(){

        $features.each(function(){
          var $feature = $(this).css({
                cursor: 'pointer'
              }),
              $text = $('.feature-text', $feature),
              $wrapText = $('<div>').css({
                position: 'relative',
                overflow: 'hidden',
                height: 0
              }).insertBefore($text).append($text),
              $link = $('a', $text),
              outTimer;

          $text.show();

          $feature.on({
            mouseenter: function()
            {
              clearTimeout(outTimer);
              $wrapText.animate({
                height: $text.outerHeight(true)
              }, 125);
            },
            mouseleave: function()
            {
              outTimer = setTimeout(function(){
                $wrapText.animate({
                  height: 0
                }, 125);
              }, 100);
            },
            click: function()
            {
              document.location = $link.href;
            }
          });
        });
      });


      /*
      Feature tiles need to scale aswell
      take sample dimensions from the
      first tile to use for scaling
       */
      $sampleContent = $featureContents.eq(0),
      $sampleImgSpace = $featureImgs.eq(0),
      innerVspace = parseInt($inner.css('padding-top')) + parseInt($inner.css('padding-bottom')),
      imageContainerWidth = $sampleImgSpace.width(),
      imageContainerHeight = $sampleImgSpace.height(),
      imageContainerRatio = imageContainerWidth / imageContainerHeight;


  scaleFeatures();
  $(window).on('resize', scaleFeatures);

  function scaleFeatures()
  {
    var vSpace = parseInt($sampleContent.css('padding-top')) + parseInt($sampleContent.css('padding-bottom')),
        hSpace = parseInt($sampleContent.css('padding-left')) + parseInt($sampleContent.css('padding-right'));

    var height = $wrap.outerHeight(true) - innerVspace - vSpace,
        width = height * imageContainerRatio;



    /* need to resize the following in each tile:
     * .feature ($features) - w + hspace / h + vspace
     * .feature-content ($featureContents) - w
     * .feature-img ($featureImgs) - h
     */

    $features.width(width + hSpace).height(height + vSpace);

    $featureContents.width(width);

    $featureImgs.height(height);
  }


});

jQuery(function($){
  var debug = true;
  var $body = $('body'),
      $header = $('#header'),
      $footer = $('#footer'),
      $hero = $('#hero'),
      $carousel = $('.carousel', $hero),
      $features = $('#home-features');

  if($hero.length===0) return;

  var eventHeroSizeChange = 'heroSizeChange',
      footerHeight = $footer.height(),
      featuresStartHeight = $features.height(),
      xtraHeightFix = 2,
      $carousel = $('.carousel', $hero),
      $slides = $('.slide', $hero),
      $slidesInner = $('.slide-inner', $hero),
      nSlides = $slides.length,
      started = false,
      currentSlide = -1,
      currentSlideWidth = 0,
      currentHeroWidth = 0,
      currentHeroHeight = 0,
      currentHeroInnerHeight = 0,
      slidePauseTime = 5000,
      slideTransTime = 1000,
      slideTimer = null,
      assetsPerSlide = 4,
      /**
       * a way to track when all assets of all
       * slides are ready to start the animation
       * (when it is 0)
       */
      slidesAssetsWaiting = assetsPerSlide * nSlides,
      nextSlide = function()
      {
        clearTimeout(slideTimer);
        if(currentSlide===-1) {
          /*
          skip slide in animation
           */
          currentSlide = 0;
          $slides.eq(currentSlide).trigger('slideInComplete');

          slideTimer = setTimeout(nextSlide, slidePauseTime);
        }else{
          var next = currentSlide + 1;
          if(next >= nSlides) next = 0;

          $carousel.animate({
            marginLeft: (0 - (next * 100)) + '%',
          }, slideTransTime, function(){
            $slides.eq(next).trigger('slideInComplete');
            $slides.eq(currentSlide).trigger('slideOutComplete');

            currentSlide = next;


            slideTimer = setTimeout(nextSlide, slidePauseTime);
          });

        }
      },
      getImgSrc = function($el){
        return $el.css('background-image').replace(/url\(['"]?(.*)['"]?\)/gi, '$1');
      };

  /**
   * Fluid widths
   */
  $carousel.width( (100 * nSlides)+'%' );
  $slides.width( (100 / nSlides)+'%' );

  function adjustSizes()
  {
    var winHeight = $(window).height(),
        headerHeight = $header.outerHeight(true) - xtraHeightFix,
        featureSpace = $features.height();

    if(winHeight < 560) winHeight = 560;

    currentHeroHeight = winHeight - headerHeight - footerHeight + xtraHeightFix;
    currentHeroInnerHeight = currentHeroHeight - featureSpace - xtraHeightFix;

    $hero.css({
      height: currentHeroHeight,
      paddingTop: headerHeight
    });
    $slidesInner.height(currentHeroInnerHeight);

    /**
     * Fire custom event for handlers to do other resizing
     * eg. see the handlers set up on the $bg elements
     */
    $.event.trigger({
      type: eventHeroSizeChange,
      width: $hero.width(),
      height: currentHeroHeight,
      innerHeight: currentHeroInnerHeight
    });
  }
  $(window).resize(adjustSizes);

  function innerImgSize(innerHeight, nativeWidth, nativeHeight, ratio)
  {
    var height = innerHeight,
        width = height * ratio;

    if(height > nativeHeight) {
      height = nativeHeight;
      width = nativeWidth;
    }

    return {
      width: width,
      height: height
    };
  };

  $slides.each(function(i){
    var $slide = $(this),
        loaded = function()
        {
          slidesAssetsWaiting--;
          if(slidesAssetsWaiting<=0 && !started) {
            started = true;
            nextSlide();
          }
        },
        /*
        If img fails still run loaded
        it's there for timing purposes
        when large images load but we want
        the final to work regardless
         */
        onImgFailed = loaded,
        $l1 = $('.l1', this),
        $l2 = $('.l2', this),
        $l3 = $('.l3', this),
        $bg = $('<img src="'+getImgSrc($slide)+'" alt="">').imgload(function(){

          var nativeWidth = $bg.width(),
              nativeHeight = $bg.height(),
              ratio = nativeWidth / nativeHeight;

          /**
           * custom event handler
           */
          $(document).on(eventHeroSizeChange, function(e){
            var height = e.height,
                width = height * ratio;

            if(width < e.width) {
              width = e.width;
              height = width / ratio;
            }

            $bg.css({
              width: width,
              height: height,
              marginTop: 0 - (height/2),
              marginLeft: 0 - (width/2),
              top: '50%',
              left: '50%'
            });
          });

          /**
           * init and inject
           */
          adjustSizes();
          $bg.prependTo($slide);
          loaded();
        }, onImgFailed).css({
          position: 'absolute',
          left: -9999
        }).appendTo($body);

    $slide.css('background-image','none');
    $.each([$l1,$l2,$l3], function(j){
      var $layer = $(this);
      if($layer.length===1) {
        $('<img src="'+getImgSrc($layer)+'" alt="">').imgload(function(){
          var $img = $(this),
              nativeWidth = $img.width(),
              nativeHeight = $img.height(),
              ratio = nativeWidth / nativeHeight;

          /*
          $l1 (0) will have an animation when the slide moves in
          going from centered no width height to target width height

          so set the init width / height to 0 and flag as locked
          and add some custom events to $slide
           */

          if(j===0) {
            $img.css({
              width: 0,
              height: 0,
              marginLeft: 0,
              left: '50%'
            }).addClass('locked');

            $slide.on({
              slideInComplete: function()
              {
                // start animation
                var targetSize = innerImgSize(currentHeroInnerHeight, nativeWidth, nativeHeight, ratio);
                targetSize.marginLeft = 0 - (targetSize.width / 2);

                $img.animate(targetSize, 500, function(){
                  $img.removeClass('locked');
                });
              },
              slideOutComplete: function()
              {
                $img.css({
                  width: 0,
                  height: 0,
                  marginLeft: 0
                }).addClass('locked');
              }
            });

          }

          /**
           * custom event handler for resizing / positioning
           */
          $(document).on(eventHeroSizeChange, function(e){
            if($img.hasClass('locked')) return;

            var size = innerImgSize(e.innerHeight, nativeWidth, nativeHeight, ratio);

            $img.css({
              width: size.width,
              height: size.height,
              marginLeft: 0 - (size.width / 2),
              left: '50%'
            });
          });

          /**
           * init and inject
           */
          adjustSizes();
          $img.css('z-index',j).appendTo($layer);
          loaded();
        }, onImgFailed).css({
          position: 'absolute',
          left: -9999
        }).appendTo($body);

        $layer.css('background-image','none');
      }else{
        onImgFailed();
      }
    });
  });
});